<pre class='metadata'>
Title: WebGPU Correspondence Reference
Shortname: webgpu-correspondence
Level: None
Status: UD
Group: webgpu
URL: https://gpuweb.github.io/gpuweb/correspondence/
!Participate: <a href="https://github.com/gpuweb/gpuweb/issues/new">File an issue</a> (<a href="https://github.com/gpuweb/gpuweb/issues">open issues</a>)
Editor: Kai Ninomiya, Google https://www.google.com, kainino@google.com, w3cid 99487
Editor: Brandon Jones, Google https://www.google.com, bajones@google.com, w3cid 87824
No Abstract: true
Markup Shorthands: markdown yes
Markup Shorthands: dfn yes
Markup Shorthands: idl yes
Markup Shorthands: css no
Assume Explicit For: yes
Boilerplate: repository-issue-tracking yes
</pre>

<style>
code {
    background: rgba(186, 186, 186, 30%);
    padding: 0 3px;
    border-radius: 4px;
}

.overlarge {
    overflow-x: unset;
}
</style>

This non-normative document provides an unofficial reference for how WebGPU names correspond
to names in other APIs. It also provides references for how to implement some parts of WebGPU
on various backend APIs. **It is not guaranteed to be correct or up-to-date.**

Correspondence or implementation strategy information not covered by this document can generally be
found in GitHub issue discussions.


# Terminology # {#Terminology}

## Resources ## {#resources}

<table class=data>
    <thead>
        <tr>
            <th>WebGPU
            <th>OpenGL/Vulkan
            <th>Metal
            <th>D3D12
    </thead>
    <tr>
        <th>uniform buffer
        <td>uniform buffer
        <td>constant memory buffer
        <td>CBV (constant buffer view)
    <tr>
        <th>storage buffer
        <td>storage buffer
        <td>device memory buffer
        <td>UAV (unordered access view) of a buffer
    <tr>
        <th>sampled texture
        <td>sampled texture/image
        <td>texture binding (texture views are also represented as textures)
        <td>SRV (shader resource view)
    <tr>
        <th>storage texture
        <td>storage texture/storage image, or storage texel buffer
        <td>device texture with read/write access
        <td>UAV (unordered access view) of a texture
    <tr>
        <th>(array or cube) layer index
        <td>cube-face and layer index
        <td>cube-face and array element
        <td>sub-resource index
</table>


# Limits # {#limits}

This section provides references for computing WebGPU's limit values in each of the three backend APIs.
These references inform the base values of these limits, as well as how implementations compute adapter limits.
User agents are not required to use these formulas and may expose whatever they want
(e.g. always choosing the base value of a limit, or bucketing devices as a fingerprinting protection).

<table class=data style="font-size: 90%">
    <thead>
        <tr>
            <th>Limit
            <th>Issue
            <th>Vulkan
            <th>Metal
            <th>D3D12
        <tr>
            <td>
            <td>
            <td>[Required Limits](https://www.khronos.org/registry/vulkan/specs/1.3/html/vkspec.html#limits-required)
            <td>[Feature Set Tables](https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf)
            <td>[Constants](https://docs.microsoft.com/en-us/windows/win32/direct3d12/constants),
                [Hardware Tiers](https://docs.microsoft.com/en-us/windows/win32/direct3d12/hardware-support),
                [Root Signature Limits](https://docs.microsoft.com/en-us/windows/win32/direct3d12/root-signature-limits)
    </thead>
    <tr>
        <th>`maxBufferSize`
        <td>[#1371](https://github.com/gpuweb/gpuweb/issues/1371)
        <td>`min(maxMemoryAllocationSize, maxBufferSize)`
        <td>`MTLDevice.maxBufferLength`
        <td>*No documented limit.* Implementations could use a constant, or determine this based on the amount of VRAM on the system as D3D11 FL11's [soft resource size limit](https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-resources-limits) does.
    <tr>
        <th>`maxTextureDimension1D`
        <td>[#1327](https://github.com/gpuweb/gpuweb/issues/1327)
        <td>`maxImageDimension1D`
        <td>`Maximum 1D texture width`
        <td>16384 = `D3D12_REQ_TEXTURE1D_U_DIMENSION`
    <tr>
        <th>`maxTextureDimension2D`
        <td>[#1327](https://github.com/gpuweb/gpuweb/issues/1327)
        <td>`min(maxImageDimension2D, maxImageDimensionCube, maxFramebufferWidth, maxFramebufferHeight, maxViewportDimensions[0], maxViewportDimensions[1], viewportBoundsRange[0], -viewportBoundsRange[1])`
        <td>min(`Maximum 2D texture width and height`, `Maximum cube map texture width and height`)
        <td>16384 = `min(D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION, D3D12_REQ_TEXTURECUBE_DIMENSION)`
    <tr>
        <th>`maxTextureDimension3D`
        <td>[#1327](https://github.com/gpuweb/gpuweb/issues/1327)
        <td>`maxImageDimension3D`
        <td>`Maximum 3D texture width, height, and depth`
        <td>2048 = `D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION`
    <tr>
        <th>`maxTextureArrayLayers`
        <td>[#1327](https://github.com/gpuweb/gpuweb/issues/1327)
        <td>`maxImageArrayLayers`
        <td>`Maximum number of layers per 1D texture array, 2D texture array, or 3D texture`
        <td>2048 = `D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION`
    <tr>
        <th>`maxBindGroups`
        <td>[#47](https://github.com/gpuweb/gpuweb/issues/47)
        <td>`maxBoundDescriptorSets`
        <td><p class=issue>It's complicated.
        <td rowspan=3>*Strategy-dependent.* Allocate the `D3D12_MAX_ROOT_COST`, minus reserved slots, across these three limits.
    <tr>
        <th>`maxDynamicUniformBuffersPerPipelineLayout`
        <td>[#406](https://github.com/gpuweb/gpuweb/issues/406)
        <td>`maxDescriptorSetUniformBuffersDynamic`
        <td>When not using argument buffers: `maxUniformBuffersPerShaderStage`

            Issue: When using argument buffers: ?
    <tr>
        <th>`maxDynamicStorageBuffersPerPipelineLayout`
        <td>[#406](https://github.com/gpuweb/gpuweb/issues/406)
        <td>`maxDescriptorSetStorageBuffersDynamic`
        <td>When not using argument buffers, `maxStorageBuffersPerShaderStage`

            Issue: When using argument buffers: ?
    <tr>
        <th>`maxBindGroupsPlusVertexBuffers`
        <td>[#2749](https://github.com/gpuweb/gpuweb/issues/2749)
        <td>No limit. Choose e.g. `max(default, maxBindGroups + maxVertexBuffers)`.
        <td>*Strategy-dependent.* When using argument buffers, `Maximum number of _____ you can access, per stage, from an argument buffer`
        <td>No limit. Choose e.g. `max(default, maxBindGroups + maxVertexBuffers)`.
    <tr>
        <th>`maxBindingsPerBindGroup`
        <td>[#3279](https://github.com/gpuweb/gpuweb/issues/3279),
            [#3864](https://github.com/gpuweb/gpuweb/issues/3864)
        <td colspan=3>Limit is arbitrary to allow implementations to treat binding space as an array.
    <tr>
        <th>`maxSamplersPerShaderStage`
        <td>[#409](https://github.com/gpuweb/gpuweb/issues/409)
        <td>`maxPerStageDescriptorSamplers`
        <td>`Maximum number of entries in the sampler state argument table, per graphics or kernel function`
        <td>`Maximum number of Samplers in all descriptor tables per shader stage`
    <tr>
        <th>`maxSampledTexturesPerShaderStage`
        <td>[#409](https://github.com/gpuweb/gpuweb/issues/409)
        <td>`maxPerStageDescriptorSampledImages`
        <td rowspan=2>*Strategy-dependent.* Allocate `Maximum number of entries in the texture argument table, per graphics or kernel function` across these two limits.
        <td>`Maximum number of Shader Resource Views in all descriptor tables per shader stage`
    <tr>
        <th>`maxStorageTexturesPerShaderStage`
        <td>[#409](https://github.com/gpuweb/gpuweb/issues/409)
        <td>*Strategy-dependent.* Choose a value &le; `maxPerStageDescriptorStorageImages`
            while adhering to [[#vulkan-maxFragmentCombinedOutputResources]].
        <td rowspan=2>*Strategy-dependent.* Allocate `Maximum number of Unordered Access Views in all descriptor tables across all stages` (guaranteed to be 64) across stages across these two limits. For example, 32 for each shader stage, split as 16 textures and 16 buffers per shader stage.
    <tr>
        <th>`maxStorageBuffersPerShaderStage`
        <td>[#409](https://github.com/gpuweb/gpuweb/issues/409)
        <td>*Strategy-dependent.* Choose a value &le; `maxPerStageDescriptorStorageBuffers`
            while adhering to [[#vulkan-maxFragmentCombinedOutputResources]].
        <td rowspan=3>*Strategy-dependent.* Allocate `Maximum number of entries in the buffer argument table, per graphics or kernel function` across these three limits.
    <tr>
        <th>`maxUniformBuffersPerShaderStage`
        <td>[#409](https://github.com/gpuweb/gpuweb/issues/409)
        <td>`maxPerStageDescriptorUniformBuffers`
        <td>`Maximum number of Constant Buffer Views in all descriptor tables per shader stage`
    <tr>
        <th>`maxVertexBuffers`
        <td>[#693](https://github.com/gpuweb/gpuweb/issues/693)
        <td>`maxVertexInputBindings`
        <td>[16](https://docs.microsoft.com/en-ca/windows/win32/api/d3d12/ns-d3d12-d3d12_input_element_desc)
    <tr>
        <th>`maxUniformBufferBindingSize`
        <td>[#803](https://github.com/gpuweb/gpuweb/issues/803)
        <td>`maxUniformBufferRange`
        <td>*No documented limit.* Use `maxBufferSize` or choose a constant.
        <td>65536 = `D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * sizeof(float4)`
    <tr>
        <th>`maxStorageBufferBindingSize`
        <td>[#1163](https://github.com/gpuweb/gpuweb/issues/1163)
        <td>`maxStorageBufferRange`
        <td colspan=2>*No documented limit.* Use `maxBufferSize` or choose a constant.
    <tr>
        <th>`minUniformBufferOffsetAlignment`
        <td>[#1863](https://github.com/gpuweb/gpuweb/issues/1863)
        <td>`minUniformBufferOffsetAlignment`
        <td>`Minimum constant buffer offset alignment`
        <td>256 = `D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT`
    <tr>
        <th>`minStorageBufferOffsetAlignment`
        <td>[#1863](https://github.com/gpuweb/gpuweb/issues/1863)
        <td>`minStorageBufferOffsetAlignment`
        <td>*No documented limit.* Use 32, which is the lowest allowed value.
        <td>32 = `max(32, D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT (16))`
    <tr>
        <th>`maxVertexAttributes`
        <td>[#693](https://github.com/gpuweb/gpuweb/issues/693)
        <td>`maxVertexInputAttributes`
        <td>*No limit.* Use `maxVertexBuffers * Maximum number of vertex attributes, per vertex descriptor`
        <td>32 = `D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT`
    <tr>
        <th>`maxVertexBufferArrayStride`
        <td>[#693](https://github.com/gpuweb/gpuweb/issues/693)
        <td>`maxVertexInputBindingStride`
        <td>*No documented limit?*
        <td>2048 B = `D3D12_SO_BUFFER_MAX_STRIDE_IN_BYTES`
    <tr>
        <th>`maxInterStageShaderVariables`
        <td>[#1962](https://github.com/gpuweb/gpuweb/issues/1962#issuecomment-1136316791)
        <td>`min(maxVertexOutputComponents // 4, maxFragmentInputComponents // 4)`
        <td>Min of:

            - `Maximum scalar or vector inputs to a fragment function`, subtract 2 for non-Apple GPUs
            - `(Maximum number of input components to a fragment function) / 4`, subtract 1 for non-Apple GPUs
        <td>30 = `min(D3D12_VS_OUTPUT_REGISTER_COUNT - 1, D3D12_PS_INPUT_REGISTER_COUNT - 2)`
    <tr>
        <th>`maxColorAttachments`
        <td>[#2820](https://github.com/gpuweb/gpuweb/issues/2820)
        <td>*Strategy-dependent.* Choose a value &le; `min(maxColorAttachments, maxFragmentOutputAttachments)`
            while adhering to [[#vulkan-maxFragmentCombinedOutputResources]].
        <td>`Maximum number of color render targets per render pass descriptor`
        <td>8 = `D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT`
    <tr>
        <th>`maxColorAttachmentBytesPerSample`
        <td>[#2965](https://github.com/gpuweb/gpuweb/issues/2965)
        <td><p class=issue>*No documented limit?*
        <td>Mostly `Maximum total render target size, per pixel, when using multiple color render targets`,
            but it's [a bit more complicated than that](https://github.com/gpuweb/gpuweb/issues/2965#issuecomment-1223792432)
        <td><p class=issue>*No documented limit?*
    <tr>
        <th>`maxComputeWorkgroupStorageSize`
        <td>[#1863](https://github.com/gpuweb/gpuweb/issues/1863)
        <td>`maxComputeSharedMemorySize`
        <td>`Maximum total threadgroup memory allocation`
        <td>[32 KiB](https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#18.6.6%20Inter-Thread%20Data%20Sharing)
    <tr>
        <th>`maxComputeInvocationsPerWorkgroup`
        <td>[#1863](https://github.com/gpuweb/gpuweb/issues/1863)
        <td>`min(maxComputeWorkGroupInvocations, product(maxComputeWorkGroupSize[0..2]))`
        <td rowspan=4>`Maximum threads per threadgroup` (but actually `maxTotalThreadsPerThreadgroup` for a given pipeline)
        <td>1024 = `D3D12_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP`
    <tr>
        <th>`maxComputeWorkgroupSizeX`
        <td>[#1898](https://github.com/gpuweb/gpuweb/issues/1898)
        <td>`min(maxComputeWorkGroupSize[0], maxComputeWorkGroupInvocations)`
        <td>1024 = `D3D12_CS_THREAD_GROUP_MAX_X`
    <tr>
        <th>`maxComputeWorkgroupSizeY`
        <td>[#1898](https://github.com/gpuweb/gpuweb/issues/1898)
        <td>`min(maxComputeWorkGroupSize[1], maxComputeWorkGroupInvocations)`
        <td>1024 = `D3D12_CS_THREAD_GROUP_MAX_Y`
    <tr>
        <th>`maxComputeWorkgroupSizeZ`
        <td>[#1898](https://github.com/gpuweb/gpuweb/issues/1898)
        <td>`min(maxComputeWorkGroupSize[2], maxComputeWorkGroupInvocations)`
        <td>64 = `D3D12_CS_THREAD_GROUP_MAX_Z`
    <tr>
        <th>`maxComputeWorkgroupsPerDimension`
        <td>[#1863](https://github.com/gpuweb/gpuweb/issues/1863)
        <td>`min(maxComputeWorkGroupCount[0..2])`
        <td><p class=issue>*No documented limit?*
        <td>65535 = `D3D12_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION`
    <tr>
        <th>Max Viewport Size (implied)
        <td>[#373](https://github.com/gpuweb/gpuweb/issues/373)
        <td>`maxViewportDimensions` (&ge; largest framebuffer attachement)
        <td><p class=issue>*No documented limit?*
        <td><p class=issue>*No documented limit?*
    <tr>
        <th>Min Viewport Bounds (implied)
        <td>[#373](https://github.com/gpuweb/gpuweb/issues/373)
        <td>`viewportBoundsRange[0]` (= -2 &times; `max(maxViewportDimensions[0..1])`)
        <td><p class=issue>*No documented limit?*
        <td>-32768 = `D3D12_VIEWPORT_BOUNDS_MIN`
        
        Note: equal to -2 &times; `maxTextureDimension2D`
    <tr>
        <th>Max Viewport Bounds (implied)
        <td>[#373](https://github.com/gpuweb/gpuweb/issues/373)
        <td>`viewportBoundsRange[1]` (= 2 &times; `max(maxViewportDimensions[0..1])` - 1)
        <td><p class=issue>*No documented limit?*
        <td>32767 = `D3D12_VIEWPORT_BOUNDS_MAX`
        
        Note: equal to 2 &times; `maxTextureDimension2D` - 1
</table>

## Vulkan `maxFragmentCombinedOutputResources` ## {#vulkan-maxFragmentCombinedOutputResources}

Choose `maxStorageBuffersPerShaderStage`, `maxStorageTexturesPerShaderStage`, and `maxColorAttachments`
such that their sum is &le; Vulkan's `maxFragmentCombinedOutputResources`.

<p class=advisement>
Warning:
`maxFragmentCombinedOutputResources` is incorrectly reported on many
[Intel, AMD, NVIDIA](https://github.com/gpuweb/gpuweb/issues/4018#issuecomment-1499725189), and
[Imagination](https://github.com/gpuweb/gpuweb/issues/3631#issuecomment-1498747606) drivers.
On these drivers, the combined limit may need to be ignored.
</p>
